package graph

import (
	"fmt"

	"github.com/goccy/go-graphviz"
	"github.com/goccy/go-graphviz/cgraph"
)

// 节点有向连接
type diLine struct {
	from *cgraph.Node
	to   *cgraph.Node
}

// OutputSVG 输出图的SVG文件
func (g *Digraph) OutputSVG(filename string) error {
	var err error
	gviz := graphviz.New()
	graph, err := gviz.Graph()
	if err != nil {
		return err
	}

	defer func() error {
		if err := graph.Close(); err != nil {
			return err
		}
		return gviz.Close()
	}()

	// 创建节点
	nodes := make(map[string]*cgraph.Node)
	g.Vertexes.Scan(func(item *Item) bool {
		node, err := graph.CreateNode(item.Vertex.GetName())
		if err != nil {
			return false
		}

		nodes[item.Vertex.GetName()] = node
		return true
	})
	if err != nil {
		return err
	}

	// 创建顶点连接
	lines := make(map[string]*diLine)
	g.Vertexes.Scan(func(item *Item) bool {
		item.Vertex.AdjacentVertexes.Scan(func(adjItem *Item) bool {
			lines[MergeName(item.Vertex.Out.Name, adjItem.Vertex.In.Name)] = &diLine{
				from: nodes[item.Vertex.GetName()],
				to:   nodes[adjItem.Vertex.GetName()],
			}
			return true
		})
		return true
	})

	// 创建边
	edges := make(map[string]*cgraph.Edge)
	g.Edges.Scan(func(item *Item) bool {
		line, ok := lines[item.Edge.GetName()]
		if !ok {
			return true
		}

		edge, err := graph.CreateEdge(item.Edge.GetName(), line.from, line.to)
		if err != nil {
			return false
		}
		edge.SetLabel(fmt.Sprintf("%d/%d", item.Edge.Api.Num, item.Edge.Api.CallCount))
		edge.SetLabelFontColor("RED")
		edges[item.Edge.GetName()] = edge
		return true
	})

	// 保存到图片
	return gviz.RenderFilename(graph, graphviz.SVG, filename)
}
